package yun.web.springmvc;

import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.io.resource.FileResource;
import cn.hutool.core.io.resource.UrlResource;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.core.env.*;
import org.yaml.snakeyaml.Yaml;
import yun.web.enjoy.template.Engine;
import yun.web.enjoy.template.Template;
import yun.web.enjoy.template.ext.directive.FileToStrDirective;

import java.util.HashMap;
import java.util.Map;

public class YunConfigurableEnvironment extends StandardEnvironment {

    JSONObject jsonObject;

    public YunConfigurableEnvironment() {
        loadConfig();
    }

    private void loadConfig() {
        String config = System.getProperty("config");
        // 默认配置
        if (config == null) {
            config = "classpath:application.yml";
            System.out.println("============ 未指定配置文件, 默认 " + config + " ============ ");
        } else {
            System.out.println("============ 已指定配置文件, " + config + " ============ ");
        }
        System.setProperty("config", config);

        UrlResource configResource = null;
        try {
            // 本地文件
            if (config.startsWith("file:")) {
                configResource = new FileResource(config.replace("file:", ""));
            }
            // classpath
            else {
                configResource = new ClassPathResource(config.replace("classpath:", ""));
            }
            String configString = resolveYmlTpl(configResource.readUtf8Str());

            jsonObject = new Yaml().loadAs(configString, JSONObject.class);
        } catch (Exception e) {
            System.err.println("加载" + config + "出错, 请检查文件是否存在, 语法是否错误");
            System.out.println();
            throw e;
        }
    }

    private String resolveYmlTpl(String string) {
        Engine engine = Engine.use("default-engine") == null ? Engine.create("default-engine") : Engine.use("default-engine");
        engine.removeDirective("file_to_str").addDirective("file_to_str", FileToStrDirective.class);

        Template tpl;
        HashMap<Object, Object> map = new HashMap<>();
        //

        // 需要获取空格数量
        //while (ReUtil.contains("#[^ ]+\\(.+\\)", string)) {
        while (string.contains("#file_to_str(")) {
            tpl = engine.getTemplateByString(string);
            string = tpl.renderToString(map);
        }
        return string;

    }


    @Override
    public String getProperty(String key) {
        Object result = JSONPath.eval(jsonObject, key);

        return result == null ? null : result.toString();
    }

    public <T> T getArray(String key) {
        Object result = JSONPath.eval(jsonObject, key);
        return result == null ? null : (T) result;
    }

    public JSONArray getJSONArray(String key) {
        JSONArray result = JSON.parseArray(JSON.toJSONString(JSONPath.eval(jsonObject, key)));
        return result;
    }

    @Override
    public String getProperty(String key, String defaultValue) {
        String value = getProperty(key);
        return value == null ? defaultValue : value;
    }

    @Override
    public <T> T getProperty(String key, Class<T> targetType) {
        return super.getProperty(key, targetType);
    }

    @Override
    public <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
        return null;
    }


    @Override
    public void setActiveProfiles(String... profiles) {

    }

    @Override
    public void addActiveProfile(String profile) {

    }

    @Override
    public void setDefaultProfiles(String... profiles) {

    }

    @Override
    public MutablePropertySources getPropertySources() {
        return null;
    }

    @Override
    public Map<String, Object> getSystemProperties() {
        return (Map) System.getProperties();
    }

    @Override
    public Map<String, Object> getSystemEnvironment() {
        return super.getSystemEnvironment();
    }

    @Override
    public void merge(ConfigurableEnvironment parent) {

    }

    @Override
    public ConfigurableConversionService getConversionService() {
        return null;
    }

    @Override
    public void setConversionService(ConfigurableConversionService conversionService) {

    }

    @Override
    public void setPlaceholderPrefix(String placeholderPrefix) {

    }

    @Override
    public void setPlaceholderSuffix(String placeholderSuffix) {

    }

    @Override
    public void setValueSeparator(String valueSeparator) {

    }

    @Override
    public void setIgnoreUnresolvableNestedPlaceholders(boolean ignoreUnresolvableNestedPlaceholders) {

    }

    @Override
    public void setRequiredProperties(String... requiredProperties) {

    }

    @Override
    public void validateRequiredProperties() throws MissingRequiredPropertiesException {

    }

    @Override
    public String[] getActiveProfiles() {
        return new String[0];
    }

    @Override
    public String[] getDefaultProfiles() {
        return new String[0];
    }

    @Override
    public boolean acceptsProfiles(String... profiles) {
        return false;
    }

    @Override
    public boolean acceptsProfiles(Profiles profiles) {
        return false;
    }

    @Override
    public boolean containsProperty(String key) {
        return false;
    }


    @Override
    public String getRequiredProperty(String key) throws IllegalStateException {
        return null;
    }

    @Override
    public <T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException {
        return null;
    }

    @Override
    public String resolvePlaceholders(String text) {
        return null;
    }

    @Override
    public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
        return super.resolveRequiredPlaceholders(text);
    }

    public boolean getBoolean(String s) {
        return "true".equals(getProperty(s));
    }
}
